home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / src / smtp / qu2sm_send.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-28  |  12.0 KB  |  485 lines

  1. /*
  2.  *     MULTI-CHANNEL MEMO DISTRIBUTION FACILITY  (MMDF)
  3.  *
  4.  *     Copyright (C) 1979,1980,1981  University of Delaware
  5.  *
  6.  *     Department of Electrical Engineering
  7.  *     University of Delaware
  8.  *     Newark, Delaware  19711
  9.  *
  10.  *     Phone:  (302) 738-1163
  11.  *
  12.  *
  13.  *     This program module was developed as part of the University
  14.  *     of Delaware's Multi-Channel Memo Distribution Facility (MMDF).
  15.  *
  16.  *     Acquisition, use, and distribution of this module and its listings
  17.  *     are subject restricted to the terms of a license agreement.
  18.  *     Documents describing systems using this module must cite its source.
  19.  *
  20.  *     The above statements must be retained with all copies of this
  21.  *     program and may not be removed without the consent of the
  22.  *     University of Delaware.
  23.  *
  24.  *
  25.  *     version  -1    David H. Crocker    March   1979
  26.  *     version   0    David H. Crocker    April   1980
  27.  *     version  v7    David H. Crocker    May     1981
  28.  *     version   1    David H. Crocker    October 1981
  29.  *
  30.  */
  31. /*                SEND FROM DELIVER TO ARPANET MACHINE
  32.  *
  33.  *  Jun 81  D. Crocker    Officially added SRI's header-transform code
  34.  *                        Removed MLFL-related code
  35.  *                        Add HDRMOD conditional compilation for code
  36.  *                        that transforms offnet addresses
  37.  *                        Moved unlink just after reopen, in d2a_send()
  38.  *  Jul 81  D. Crocker    Only call am_cend if txtcpy was successful
  39.  *  Aug 81  D. Crocker    d2a_send() had fclose's w/out fp validity test
  40.  *
  41.  *      -----------------------------------------------------------
  42.  *
  43.  *  Feb 83  Doug Kingston       *** Total Rewrite, Some Fragments Used ***
  44.  *  Nov 83  Steve Kille         Add throughput and UCL changes
  45.  */
  46.  
  47. #include "util.h"
  48. #include "mmdf.h"
  49. #include "ch.h"
  50. #include "ap.h"
  51. #include "smtp.h"
  52.  
  53. extern struct ll_struct   *logptr;
  54. extern Chan *chanptr;
  55. extern char *supportaddr;
  56.  
  57. extern char *sm_curname;
  58.  
  59. extern long qu_msglen;
  60. extern long sm_hostid();
  61. extern struct sm_rstruct sm_rp;
  62. extern char *strdup();
  63. extern char *strncpy();
  64. extern char *ap_p2s();
  65. extern char *blt();
  66. extern time_t time();
  67.  
  68. extern int ap_outtype;
  69.  
  70. LOCFUN qu2sm_each(), qu2sm_txtcpy();
  71.  
  72. LOCVAR time_t start_time;
  73. LOCVAR short sm_fromsent;
  74. LOCVAR int nadrs;
  75. LOCVAR char *sender = (char *)NULL;
  76.  
  77. LOCVAR struct rp_construct
  78.     rp_bdrem =
  79. {
  80.     RP_BHST, 'B', 'a', 'd', ' ', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e',
  81.     ' ', 'f', 'r', 'o', 'm', ' ', 'r', 'e', 'm', 'o', 't', 'e', ' ',
  82.     's', 'i', 't', 'e', '\0'
  83. }          ,
  84.     rp_adr  =
  85. {
  86.     RP_AOK, 'a', 'd', 'd', 'r', 'e', 's', 's', ' ', 'o', 'k', '\0'
  87. },
  88.     rp_gdtxt =
  89. {
  90.     RP_MOK, 't', 'e', 'x', 't', ' ', 's', 'e', 'n', 't', ' ', 'o', 'k', '\0'
  91. },
  92.     rp_noop =
  93. {
  94.     RP_NOOP, 's', 'u', 'b', '-', 'l', 'i', 's', ' ', 'n', 'o', 't', ' ',
  95.     's', 'p', 'e', 'c', 'i', 'a', 'l', '\0'
  96. },
  97.     rp_dhst =
  98. {
  99.     RP_DHST, 'R', 'e', 'm', 'o', 't', 'e', ' ', 'h', 'o', 's', 't', ' ',
  100.     'u', 'n', 'a', 'v', 'a', 'i', 'l', 'a', 'b', 'l', 'e', '\0'
  101. },
  102.     rp_kild =
  103. {
  104.     RP_DHST, 'n', 'o', ' ', 'v', 'a', 'l', 'i', 'd', ' ', 'a', 'd', 'd',
  105.     'r', 'e', 's', 's', 'e', 's', '\0'
  106. };
  107.  
  108. /* */
  109.  
  110. qu2sm_send ()             /* overall mngmt for batch of msgs    */
  111. {
  112.     short   result;
  113.     char    info[LINESIZE];
  114.     char    sendbuf[ADDRSIZE];
  115.  
  116. #ifdef DEBUG
  117.     ll_log (logptr, LLOGBTR, "qu2sm_send ()");
  118. #endif
  119.  
  120.     if (rp_isbad (result = qu_pkinit ()))
  121.     return (result);
  122.  
  123.     sm_curname = (char *) 0;
  124.  
  125.     /*
  126.      *  While there are messages to process ...
  127.      */
  128.     for(;;){
  129.     AP_ptr  loctree, domtree, routree, sendtree;
  130.     AP_ptr  ap_s2tree(), ap_normalize();
  131.  
  132.     result = qu_rinit (info, sendbuf, chanptr -> ch_apout);
  133.     if(rp_gval(result) == RP_NS){
  134.         qu_rend();
  135.         continue;
  136.     }
  137.     else if(rp_gval(result) == RP_DONE)
  138.         break;
  139.     if (rp_gval(result) == RP_FIO)          /* Can't open message file */
  140.         continue;
  141.     else if (rp_gval(result) != RP_OK)      /* Some other error */
  142.         break;
  143.  
  144. #ifdef DEBUG
  145.     ll_log (logptr, LLOGBTR, "from qu_rinit (%s)", sendbuf);
  146. #endif
  147.     if (sender != (char *)NULL)
  148.         free (sender);
  149.  
  150.     if ( sendbuf[0] == '\0' ||
  151.         (sendtree = ap_s2tree( sendbuf )) == (AP_ptr) NOTOK) {
  152.         printx("return address unparseable, using Orphanage\n");
  153.         fflush(stdout);
  154.         sender = strdup (supportaddr);
  155.     } else {
  156.         sendtree = ap_normalize (chanptr -> ch_lname,
  157.                 chanptr  -> ch_ldomain, sendtree, chanptr);
  158.         if(sendtree == (AP_ptr)MAYBE){
  159.             result = RP_NS;
  160.             goto bugout;
  161.         }
  162.         ap_t2parts (sendtree, (AP_ptr *)0, (AP_ptr *)0, &loctree, &domtree, &routree);
  163.         sender = ap_p2s ((AP_ptr)0, (AP_ptr)0, loctree, domtree, routree);
  164.         if(sender == (char *)MAYBE){
  165.             result = RP_NS;
  166.             goto bugout;
  167.         }
  168.         ap_outtype = chanptr -> ch_apout;
  169.         ap_sqdelete( sendtree, (AP_ptr) 0 );
  170.         ap_free( sendtree );
  171.     }
  172.  
  173.     if (rp_isbad (result = qu2sm_each ()))
  174.         break;
  175.  
  176.     qu_rend();              /* Cleans up after header conversion... */
  177.     }
  178.     qu_rend();
  179.  
  180.     if (sm_curname != (char *) 0)
  181.     sm_nclose (OK);
  182.  
  183.     if (rp_gval(result) != RP_DONE)
  184.     {
  185.     ll_log (logptr, LLOGFAT, "not DONE (%s)", rp_valstr (result));
  186.     return (RP_RPLY);         /* catch protocol errors              */
  187.     }
  188.  
  189.     qu_pkend ();                  /* done getting messages              */
  190.     return (result);
  191.  
  192. bugout:
  193.     qu_rend();
  194.     if (sm_curname != (char *) 0)
  195.     sm_nclose (OK);
  196.     qu_pkend ();                  /* done getting messages              */
  197.     return (result);
  198. }
  199. /* */
  200.  
  201. LOCFUN
  202.     qu2sm_each ()             /* send copy of text per address      */
  203. {
  204.     RP_Buf  thereply;
  205.     short   result;
  206.     short   len;
  207.     char    host[ADDRSIZE];
  208.     char    adr[ADDRSIZE];
  209.     char     *newname;
  210.  
  211. #ifdef DEBUG
  212.     ll_log (logptr, LLOGBTR, "qu2sm_each()");
  213. #endif
  214.  
  215.     time (&start_time);
  216.  
  217.     sm_fromsent = FALSE;
  218.     nadrs = 0;
  219.  
  220.     /*
  221.      *  For every address in the message ...
  222.      */
  223.     while( 1 ) {
  224.     result = qu_radr (host, adr);
  225.     if (rp_isbad (result))
  226.         return (result);      /* get address from Deliver           */
  227.  
  228. /*  check for end of address sub-list.  if channel is relay, then
  229.  *  sub-list reference is not meaningful.  otherwise, different
  230.  *  sub-lists reference different hosts to connect to.
  231.  */
  232.     switch (rp_gval (result))
  233.     {
  234.         case RP_HOK:          /* end of sub-list */
  235.         if (chanptr -> ch_host != NORELAY)
  236.         {                 /* different host refs => diff dests  */
  237.             qu_wrply ((RP_Buf *) &rp_noop, sizeof rp_noop);
  238.             break;
  239.         }                 /* else DROP ON THROUGH */
  240.         case RP_DONE:         /* end of full address list           */
  241.         if (nadrs == 0)
  242.         {
  243.             /*
  244.              *  Theoretically we would break the connection here since
  245.              *  the next host is a different host, except that it may
  246.              *  be flaged and the host after that might be this one.
  247.              *  Basic rule: don't break a connection until you have to.
  248.              */
  249.             qu_wrply ((RP_Buf *) &rp_kild, sizeof rp_kild);
  250.  
  251.             if (sm_curname != (char *) 0)
  252.             {
  253.             if (rp_isbad (sm_cmd ("RSET", SM_RTIME)))
  254.                 break;
  255. /********* should be:   if (sm_rp.sm_rval != 250) *******/
  256.             if (sm_rp.sm_rval < 200 || sm_rp.sm_rval > 299)
  257.                 sm_nclose( NOTOK ); /* Give up on it for now */
  258.             }
  259.         }
  260.         else if (sm_curname != (char *) 0)
  261.         {
  262.             nadrs = 0;      /* reset, in case this is only a hend */
  263.             qu2sm_txtcpy(&thereply);
  264.             ll_log(logptr, LLOGFTR, "txtcpy reply (%o) (%s)",
  265.                 thereply.rp_val, thereply.rp_line);
  266.             qu_wrply (&thereply, sizeof (thereply.rp_val)
  267.                   + strlen(thereply.rp_line));
  268.         } else {
  269.             /* Some addrs were send, but connection went bad */
  270.             qu_wrply((RP_Buf *)&rp_bdrem, sizeof rp_bdrem);
  271.         }
  272.         sm_fromsent = FALSE;
  273.         if (rp_gval (result) == RP_HOK)
  274.             continue;           /* more to process  */
  275.  
  276.         return (RP_OK);         /* END for this message */
  277.  
  278.         default:            /* actually have an address */
  279.         if(( newname =  (chanptr->ch_host == NORELAY ?
  280.            host : chanptr->ch_host)) == (char *) 0)
  281.         {
  282.             qu_wrply ((RP_Buf *)&rp_dhst, sizeof rp_dhst);
  283.             break;
  284.         }
  285.  
  286.         if (!lexequ (sm_curname, newname))
  287.         {
  288.             if (sm_curname != (char *) 0)
  289.             sm_nclose (OK);
  290.  
  291.             if( rp_isbad(sm_nopen( newname)))
  292.             {
  293.             qu_wrply((RP_Buf *)&rp_dhst, sizeof rp_dhst);
  294.             break;
  295.             }
  296.  
  297.         }
  298.  
  299.         if( sm_fromsent == FALSE ) {
  300.             if (rp_isbad (sm_wfrom (sender))) {
  301.             if (rp_isbad (sm_rpcpy(&thereply, &len)))
  302.                 qu_wrply((RP_Buf *)&rp_bdrem, sizeof rp_bdrem);
  303.             else
  304.                 qu_wrply (&thereply, len);
  305.             break;
  306.             }
  307.             sm_fromsent = TRUE;
  308.         }
  309.  
  310.         if (sm_wto (host, adr) == RP_DHST
  311.           || rp_isbad (sm_rpcpy (&thereply, &len))) {
  312.             qu_wrply ((RP_Buf *) &rp_bdrem, sizeof rp_bdrem);
  313.             break;
  314.         }
  315.         switch (rp_gval (thereply.rp_val))
  316.         {                 /* was address acceptable?            */
  317.             case RP_AOK:
  318.             nadrs++;
  319.             qu_wrply ((RP_Buf *) &rp_adr, sizeof rp_adr);
  320.             continue;
  321.  
  322.             case RP_PARM:
  323.             case RP_USER:
  324.             case RP_NO:
  325.             break;    /* report failure and continue        */
  326.  
  327.             case RP_RPLY:
  328.             ll_log (logptr, LLOGFAT, "unusual return: (%s)%s",
  329.                 rp_valstr (thereply.rp_val), thereply.rp_line);
  330.             break;    /* notify deliver */
  331.         }
  332.  
  333.         qu_wrply (&thereply, len);
  334.                   /* notify deliver */
  335.     }
  336.     }
  337.     /* NOTREACHED */
  338. }
  339. /* */
  340.  
  341. LOCFUN
  342.     qu2sm_txtcpy (rp)     /* copy the text of the message       */
  343. RP_Buf *rp;
  344. {
  345.     int       len;
  346.     short     result;
  347.     char      buffer[BUFSIZ];
  348.     long      bytecount;
  349.     time_t    start_txt,
  350.         end_txt,
  351.         time_eff,
  352.         time_txt;
  353.  
  354. #ifdef DEBUG
  355.     ll_log (logptr, LLOGBTR, "qu2sm_txtcpy()");
  356. #endif
  357.  
  358.     qu_rtinit (0L);
  359.     sm_fromsent = FALSE;
  360.     nadrs = 0;
  361.     if (rp_isbad (sm_cmd ("DATA", SM_DTIME))) {
  362.     blt ((char *)&rp_bdrem, (char *) rp, sizeof rp_bdrem);
  363.     return;
  364.     }
  365.  
  366.     switch( sm_rp.sm_rval ) {
  367.     case 354:
  368.     break;          /* Go ahead and send mail */
  369.  
  370.     case 500:
  371.     case 501:
  372.     case 503:
  373.     case 554:
  374.     rp->rp_val = RP_NDEL;
  375.     if (sm_rp.sm_rgot)
  376.         strncpy (rp->rp_line, sm_rp.sm_rstr, sm_rp.sm_rlen);
  377.     else
  378.         strcpy (rp->rp_line, "Unknown Problem");
  379.     return;
  380.  
  381.     case 421:
  382.     case 451:
  383.     default:
  384.     rp->rp_val = RP_AGN;
  385.     if (sm_rp.sm_rgot)
  386.         strncpy (rp->rp_line, sm_rp.sm_rstr, sm_rp.sm_rlen);
  387.     else
  388.         strcpy (rp->rp_line, "Unknown Problem");
  389.     return;
  390.     }
  391.  
  392.     printx ("sending...:");
  393.     fflush (stdout);
  394.  
  395.     bytecount = 0;
  396.     time (&start_txt);
  397.  
  398.     len = sizeof(buffer);
  399.     while ((rp_gval (result = qu_rtxt (buffer, &len))) == RP_OK)
  400.     {
  401.     if (setjmp(timerest)) {
  402.         break;
  403.     }
  404.     s_alarm (SM_BTIME);
  405.     result = sm_wstm (buffer, len);
  406.     s_alarm (0);
  407.     bytecount = bytecount + len;
  408.     if (rp_isbad (result))
  409.         break;
  410.     printx (".");
  411.     fflush (stdout);
  412.     if (rp_gval (result) != RP_OK) {
  413.         blt ((char *)&rp_bdrem, (char *) rp, sizeof rp_bdrem);
  414.         return;
  415.     }
  416.     len = sizeof(buffer);
  417.     }
  418.  
  419.     bytecount = bytecount +  len;
  420.  
  421.     if (rp_isbad (result) || rp_gval (result) != RP_DONE) {
  422.     blt ((char *)&rp_bdrem, (char *) rp, sizeof rp_bdrem);
  423.     return;
  424.     }
  425.  
  426.     /* Kludge: the sm_wstm function will make sure the last char is a NL */
  427.     if (setjmp(timerest)) {
  428.     blt ((char *)&rp_bdrem, (char *) rp, sizeof rp_bdrem);
  429.     return;
  430.     }
  431.     s_alarm (SM_TTIME);
  432.     result = sm_wstm ((char *)0, 0);    /* MAGIC options */
  433.     s_alarm( 0 );
  434.     if (rp_isbad (result)) {
  435.     blt ((char *)&rp_bdrem, (char *) rp, sizeof rp_bdrem);
  436.     return;
  437.     }
  438.  
  439.     printx (" ");
  440.     if( rp_isbad( sm_cmd( ".", SM_PTIME + (3*nadrs) ))) {
  441.     rp->rp_val = RP_BHST;
  442.     strcpy (rp->rp_line, "Bad response to final dot");
  443.     return;
  444.     }
  445.  
  446.     time (&end_txt);
  447.     time_txt = end_txt - start_txt;
  448.     time_eff = end_txt - start_time;
  449.  
  450.     ll_log (logptr, LLOGFST,
  451.         "tpt: data = (%ld) bytes/sec, eff =  (%ld) bytes/sec",
  452.         bytecount / (time_txt ? time_txt : 1), 
  453.         bytecount / (time_eff ? time_eff : 1));
  454.  
  455.  
  456.     time (&start_time);
  457.  
  458.     switch( sm_rp.sm_rval ) {
  459.     case 250:
  460.     case 251:
  461.     blt ((char *)&rp_gdtxt, (char *)rp, sizeof rp_gdtxt);
  462.     return;
  463.  
  464.     case 552:
  465.     case 554:
  466.     rp->rp_val = RP_NDEL;
  467.     if (sm_rp.sm_rgot)
  468.         strncpy (rp->rp_line, sm_rp.sm_rstr, sm_rp.sm_rlen);
  469.     else
  470.         strcpy (rp->rp_line, "Unknown Problem");
  471.     return;
  472.  
  473.     case 421:
  474.     case 451:
  475.     case 452:
  476.     default:
  477.     rp->rp_val = RP_AGN;
  478.     if (sm_rp.sm_rgot)
  479.         strncpy (rp->rp_line, sm_rp.sm_rstr, sm_rp.sm_rlen);
  480.     else
  481.         strcpy (rp->rp_line, "Unknown Problem");
  482.     return;
  483.     }
  484. }
  485.